
cmspad.core = {
	nls: {
		PORTLET_NAME_NOT_FOUND: 'Portlet Name Not Found: ',
		FUNCTION_NAME_NOT_FOUND: 'Portlet Function Name Not Found: ',
		RECEIVED_DATA: 'Received Data: ',
		INVALID_RESPONSE: 'Remote server returns invalid data: ',
		INVALID_COMMAND: 'Can not execute command: ',
		ELEMENT_NOT_FOUND: 'Element Not Found: '
	},
	_workId: '_cmspad_' + new Date().getTime(),
	_depth: 0,
	ResponseErrors: ['400', '401', '402', '403', '404', '500', '501', '502', '503'],
	getFormData: function(frm, up){
		var objForm;
		var submitDisabledElements = false;
		if (arguments.length > 1 && arguments[1] == true) {
			submitDisabledElements = true;
		}
		var prefix = '';
		if (arguments.length > 2) {
			prefix = arguments[2];
		}
		if (typeof(frm) == 'string') {
			objForm = cmspad.$(frm);
		} else {
			objForm = frm;
		}
		var sXml = '{';
		if (objForm && objForm.tagName.toUpperCase() == 'FORM') {
			var formElements = objForm.elements;
			var formArrays = new Array();
			for (var i = 0; i < formElements.length; i++) {
				if (!formElements[i].name) {
					continue;
				}
				if (formElements[i].name.substring(0, prefix.length) != prefix) {
					continue;
				}
				if (formElements[i].type && (formElements[i].type == 'radio' || formElements[i].type == 'checkbox') && formElements[i].checked == false) {
					continue;
				}
				if (formElements[i].disabled && formElements[i].disabled == true && submitDisabledElements == false) {
					continue;
				}
				var name = formElements[i].name;
				if (name) {
					if (sXml != '{' && sXml.substring(sXml.length - 1) != ',') {
						sXml += ',';
					}
					if (formElements[i].type == 'select-multiple') {
						sXml += '"' + (up ? encodeURIComponent(name) : name) + '":[';
						for (var j = 0, l = formElements[i].length; j < l; j++) {
							if (formElements[i].options[j].selected == true) {
								sXml += '"' + encodeURIComponent(formElements[i].options[j].value) + '"';
							}
							if(j < l - 1){
								sXml += ',';
							}
						}
						sXml += ']';
					} else {
						if (name.substring(name.length - 2) == '[]') {
							name = name.substring(0, name.length - 2);
							var formArray = formArrays[name];
							if (formArray == undefined) {
								formArray = new Array();
							}
							formArray[formArray.length] = encodeURIComponent(formElements[i].value);
							formArrays[name] = formArray;
						} else {
							sXml += '"' + encodeURIComponent(name) + '":"' + encodeURIComponent(formElements[i].value)+ '"';
						}
					}
				}
			}
			for(name in formArrays){
				sXml += (sXml.substring(sXml.length - 1) != ','?',':'') + '"' + (up ? encodeURIComponent(name) : name) + '":[';
				formArray = formArrays[name];
				for(i = 0,l = formArray.length;i < l;i++){
					sXml += '"' + (up ? encodeURIComponent(formArray[i]) : formArray[i]) + '"';
					if(i < l - 1){
						sXml += ',';
					}
				}
				sXml += ']';
			}
			delete formArrays;
		}
		sXml += '}';
		return sXml;
	},
	_objectToJson: function(obj){
		if(typeof(obj) == 'string'){
			return '"' + obj + '"';
		}else if(obj instanceof Array){
			var sXml = '[';
			for(i = 0, l = obj.length;i < l;i++){
				sXml += this._objectToJson(obj[i]);
				if(i < l - 1){
					sXml += ',';
				} 
			}
			sXml += ']';
			return sXml;
		}else{
			var sXml = '{';
			for (i in obj) {
				try {
					if (i == 'constructor') {
						continue;
					}
					if (i == '______array') {
						continue;
					}
					if (obj[i] && typeof(obj[i]) == 'function') {
						continue;
					}
					var key = i;
					var value = obj[i];
					if (value && typeof(value) == 'object' && this._depth <= 50) {
						this._depth++;
						value = this._objectToJson(value);
						this._depth--;
					}
					sXml += '"' + key + '":"' + value + '",';
				} catch (e) {
				}
			}
			sXml += '}';
			return sXml;
		}
	},
	_onFunctionCalling: function(func){
		if (this.onFunctionCalling) {
			this.onFunctionCalling(func);
		}
	},
	_onFunctionCalled: function(func, text){
		this._cmspad_view_func();
		this._cmspad_form_func();
		this._cmspad_link_func();
		if (this.onFunctionCalled) {
			this.onFunctionCalled(func, text);
		}
	},
	getPostData: function(sFunction, aArgs){
		var postTime = new Date().getTime();
		var postData = 'cpd=' + encodeURIComponent(sFunction) + '&cpdt=' + (cmspad.security.encrypt?cmspad.security.encrypt(String(postTime)):postTime);
		var postKey = null;
		if (aArgs) {
			for (var i = 0, l = aArgs.length; i < l; i++) {
				value = aArgs[i];
				if (typeof(value) == 'object') {
					value = this._objectToJson(value);
				}
				if (cmspad.security.encrypt) {
					if(!postKey){
						postKey = cmspad.security.md5(sFunction + '&' + postTime);
					}
					value = cmspad.security.encrypt(value, postKey);
				} else {
					value = encodeURIComponent(value);
				}
				postData += '&cpda[]=' + value;
			}
		}
		delete postTime;
		delete postData;
		delete postKey;
		return postData;
	},
	_call: function(sFunction, aArgs){
		var i, l, value;
		var cpdp = cmspad.REQUEST_URI.substring(0,1) != '/';
		var uri = cpdp?(cmspad.DOCUMENT_ROOT + '/kernel/index.php'):cmspad.REQUEST_URI;
		var postData = cpdp?('cpdp=' + encodeURIComponent(cmspad.REQUEST_URI) + '&'):'';
		postData += this.getPostData(sFunction, aArgs);
		cmspad.ajax.post(uri, {
			onready: function(){
				cmspad.core._onFunctionCalling(sFunction);
			},
			success: function(r){
				if(r.responseText){
					var v;
					if (cmspad.security.decrypt) {
						v = cmspad.security.decrypt(r.responseText);
					}else{
						v = r.responseText;
					}
					if (v) {
						cmspad.core._processResponse(sFunction, eval('(' + v + ')'));
					} else {
						var errmsg = cmspad.nls.STATUS_CODE + r.status + '\n\n' + cmspad.core.nls.RECEIVED_DATA + r.responseText;
						cmspad.console.error(errmsg);
					}
				}else{
					//No return?
				}
			},
			failure: function(r, a){
				var errmsg = cmspad.nls.STATUS_CODE + r.status + '\n\n' + cmspad.nls.ERROR_MESSAGE + r.statusText;
				cmspad.console.error(errmsg);
			}
		}, postData);
		return true;
	},
	_getHtmlData: function(html){
		var tmpAjax = cmspad.$(this._workId);
		if (!tmpAjax) {
			tmpAjax = document.createElement('div');
			tmpAjax.setAttribute('id', this._workId);
			tmpAjax.style.display = 'none';
			tmpAjax.style.visibility = 'hidden';
			document.body.appendChild(tmpAjax);
		}
		tmpAjax.innerHTML = html;
		var browserHTML = tmpAjax.innerHTML;
		tmpAjax.innerHTML = '';
		return browserHTML;
	},
	_willChange: function(element, attribute, newData){
		if (!document.body) {
			return true;
		}
		if (attribute == 'innerHTML') {
			newData = this._getHtmlData(newData);
		}
		elementObject = cmspad.$(element);
		if (elementObject) {
			var oldData;
			eval('oldData=cmspad.$(\'' + element + '\').' + attribute);
			if (newData !== oldData) {
				return true;
			}
		}
		return false;
	},
	viewSource: function(){
		return '<html>' + document.getElementsByTagName('HTML')[0].innerHTML + '</html>';
	},
	_processResponse: function(func, xml){
		this._callbackResponse(xml);
		this._onFunctionCalled(func, xml);
	},
	_callbackResponse: function(obj){
		if (obj == null) {
			return;
		}
		if(obj instanceof Array){
			for(var i = 0, l = obj.length;i < l;i++){
				this._parseObject(obj[i], i);
			}
		}else{
			this._parseObject(obj, 0);
		}
	},
	_parseObject: function(obj, ind){
		if(obj.n){
			var cmd = obj.n;
			var id = obj.t;
			var property = obj.p;
			var type = obj.c;	
			if(obj.v){
				var objElement = cmspad.$(id);
				var data;
				var indice = 0;
				if(typeof(obj.v) == 'string'){
					data = obj.v;
				}else{
					data = new Array();
					for(i in obj.v){
					  data[indice++] = obj.v[i];
					}
				}
				try {
					switch (cmd) {
						case 'cc':
							var ony = obj.v.y;
							var onn = obj.v.n;
							if(confirm(obj.v.q)){
								if(ony){
									eval(ony);
								}
							}else{
								if(onn){
									eval(onn);
								}
							}
							delete ony;
							delete onn;
							break;
						case 'al':
							alert(data);
							break;
						case 'js':
							eval(data);
							break;
						case 'jc':
							var scr = id + '(';
							if (data[0] != null) {
								scr += 'data[0]';
								for (var l = 1; l < data.length; l++) {
									scr += ',data[' + l + ']';
								}
							}
							scr += ');';
							eval(scr);
							delete scr;
							break;
						case 'it':
							cmspad.includeScript(data);
							break;
						case 'ie':
							cmspad.includeStyle(data);
							break;
						case 'as':
							if (this._willChange(id, property, data)) {
								if (!window.addEventListener || property != 'bind') {
									eval('objElement.' + property + '=data;');
								} else {
									eval('objElement.setAttribute(\'' + property + '\',data);');
								}
							}
							break;
						case 'ap':
							eval('objElement.' + property + '+=data;');
							break;
						case 'pp':
							eval('objElement.' + property + '=data+objElement.' + property);
							break;
						case 'rp':
							var search = obj.v.s;
							data = obj.v.r;
							cmspad.replace(id, property, search, data);
							delete search;
							break;
						case 'rm':
							cmspad.remove(id);
							break;
						case 'ce':
							cmspad.create(id, data, property);
							break;
						case 'ib':
							cmspad.insertBefore(id, data, property);
							break;
						case 'ia':
							cmspad.insertAfter(id, data, property);
							break;
						case 'ci':
							cmspad.createInput(id, type, data, property);
							break;
						case 'ii':
							cmspad.insertInputBefore(id, type, data, property);
							break;
						case 'iia':
							cmspad.insertInputAfter(id, type, data, property);
							break;
						case 'st':
							cmspad.style(id, property, data);
							break;
						case 'ts':
							cmspad.defer(data, id, property);
							break;
						case 'ae':
							cmspad.addEvent(id, property, data);
							break;
						case 're':
							cmspad.removeEvent(id, property, data);
							break;
					}
				} catch (e) {
					cmspad.console.error('[' + ind + '] ' + cmspad.core.nls.INVALID_COMMAND + cmd + ', ' + cmspad.nls.ERROR_MESSAGE + '\n\n' + e.name + ': ' + e.message + '\n' + (id && !objElement ? cmspad.core.nls.ELEMENT_NOT_FOUND + id + '\n' : ''));
				}
				delete objElement;
				delete data;
				delete indice;
			}
			delete cmd;
			delete id;
			delete property;
			delete type;
		}
		delete obj;
		delete i;
	},
	///////////////////////// File Uploading Functions /////////////////////////
	_newSessionID: function(){
		var sessionID;
		sessionID = new String(new Date().getTime());
		var random = new String(Math.random()).substr(2);
		sessionID = sessionID + random;
		return sessionID;
	},
	_upload: function(rpcFunc, form, url, time){
		if (!form) {
			return false;
		}
		if (form.encoding.toLowerCase() != 'multipart/form-data') {
			form.encoding = 'multipart/form-data';
		}
		if (form.method.toLowerCase() != 'post') {
			form.method = 'post';
		}
		var newSessionID = this._newSessionID();
		if (!url) {
			url = cmspad.REQUEST_URI;
		}
		url += '&cpd=' + encodeURIComponent(rpcFunc);
		if(cmspad.security.encrypt){
			url += '&cpdt=' + cmspad.security.encrypt(String(time));
		}else{
			url += '&cpdt=' + time;
		}
		this._onFunctionCalling(rpcFunc);
		form.action = url;
		var iframeName = form.id + newSessionID;
		var iframe;
		if ((iframe = document.getElementById(iframeName))) {
			document.body.removeChild(iframe);
		}
		iframe = cmspad.createFrame(iframeName, iframeName, 'about:blank');
		form.target = iframeName;
		var xmlDoc, responseText;
		if (typeof iframe.onreadystatechange == 'object') {
			iframe.onreadystatechange = function(){
				if (iframe.readyState == 'complete' && !iframe.loaded) {
					iframe.loaded = true;
					xmlDoc = document.frames(iframe.id);
					if (xmlDoc.window.document.location != iframe.src) {
						responseText = xmlDoc.window.document.body.innerText;
						cmspad.core._uploadResponse(responseText, iframe);
						cmspad.core._onFunctionCalled(rpcFunc, responseText);
					}
				}
			}
		} else {
			iframe.onload = function(){
				xmlDoc = iframe.contentWindow;
				if (xmlDoc.window.document.location != iframe.src) {
					responseText = xmlDoc.document.body.innerHTML;
					cmspad.core._uploadResponse(responseText, iframe);
					cmspad.core._onFunctionCalled(rpcFunc, responseText);
				}
			}
		}
	},
	_uploadResponse: function(responseText, iframeObj){
		var error = false;
		if (responseText) {
			var data = responseText.replace(/(^<pre>)|(<\/pre>$)/g, '');
			if(cmspad.security.decrypt){
				data = cmspad.security.decrypt(data, cmspad.SECURITY_KEY);
			}
			var v = eval('(' + data + ')');
			if(v){
				try {
					this._processResponse('_form', v);
				} catch (e) {
					error = true;
				}
			}else{
				error = true;
			}
		} else {
			error = true;
		}
		if (error) {
			this._uploadFaild(responseText);
			delete responseText;
		} else {
			this._uploadSuccess();
		}
		setTimeout(function(){
			document.body.removeChild(iframeObj);
		}, 500);
	},
	_uploadFaild: function(responseText){
		var errorString = cmspad.core.nls.INVALID_RESPONSE + responseText;
		var trimmedResponseText = responseText.replace(/^\s+/g, '');
		trimmedResponseText = trimmedResponseText.replace(/\s+$/g, '');
		cmspad.console.error(errorString);
	},
	_uploadSuccess: function(){
	},
	_arrayContainsValue: function(array, valueToCheck){
		for (i in array) {
			if (array[i] == valueToCheck) {
				return true;
			}
		}
		return false;
	},
	//////////////////////////////// Default Functions //////////////////////////
	_cmspad_regexp: new RegExp('\\s*([0-9a-zA-Z_]+)\\s*\\.\\s*([0-9a-zA-Z_]+)\\s*[\\(]{0,1}\\s*([^\\(\\):]*)\\s*[\\)]{0,1}\\s*[:]{0,1}\\s*(.*)\\s*'),
	getExprData: function(e, p){
		values = this._cmspad_regexp.exec(e);
		if (values[1] == '') {
			cmspad.console.error(cmspad.core.nls.PORTLET_NAME_NOT_FOUND + e);
			return null;
		}
		if (values[2] == '') {
			cmspad.console.error(cmspad.core.nls.FUNCTION_NAME_NOT_FOUND + e);
			return null;
		}
		if (values[3] == '') {
			values[3] = null;
		}
		if (values[4] == '') {
			values[4] = null;
		} else {
			values[4] = values[4].replace(/(^\s*)|(\s*$)/g, '');
			if ((typeof p == undefined) || p === true) {
				endc = values[4].substring(values[4].length - 1);
				switch (endc) {
					case ')':
						values[4] += ';';
						break;
					case ';':
						break;
					default:
						values[4] += '();';
						break;
				}
			}
		}
		return {
			portlet: values[1],
			method: values[2],
			arguments: values[3],
			validator: values[4]
		};
	},
	_cmspad_bind_func: function(d){
		b = d.getAttribute('bind');
		if (b) {
			return this.getExprData(b);
		} else {
			return null;
		}
	},
	_cmspad_view_func: function(){
		views = new Array();
		ds = document.getElementsByTagName('div');
		for (i = 0, l = ds.length; i < l; i++) {
			d = ds[i];
			if (!d.isBindSet) {
				if (!d.id) {
					d.id = d.tagName + Math.round(Math.random() * 1000000);
				}
				b = this._cmspad_bind_func(d);
				if (b) {
					if (b.arguments) {
						views[views.length] = d.id + ':' + b.portlet + '.' + b.method + '(' + b.arguments + ')';
					} else {
						views[views.length] = d.id + ':' + b.portlet + '.' + b.method + '()';
					}
				}
				delete b;
				// Set portlet event flag.
				if (!d.isBindSet) {
					d.refresh = function(){
						var b = cmspad.core._cmspad_bind_func(d);
						if (b) {
							if (b.arguments) {
								cmspad_view(d.id, b.portlet, b.method, b.arguments);
							} else {
								cmspad_view(d.id, b.portlet, b.method);
							}
						}
						delete b;
					};
					if (d.addEventListener) {
						d.addEventListener('DOMAttrModified', function(e){
							if (e.attrName == 'bind') {
								b = cmspad.core._cmspad_bind_func(this);
								if (b) {
									if (b.arguments) {
										cmspad_view(this.id, b.portlet, b.method, b.arguments);
									} else {
										cmspad_view(this.id, b.portlet, b.method);
									}
								}
								delete b;
							}
							return true;
						}, false);
					} else if (d.attachEvent) {
						d.attachEvent('onpropertychange', function(){
							if (event.propertyName == 'bind') {
								d = event.srcElement;
								b = cmspad.core._cmspad_bind_func(d);
								if (b) {
									if (b.arguments) {
										cmspad_view(d.id, b.portlet, b.method, b.arguments);
									} else {
										cmspad_view(d.id, b.portlet, b.method);
									}
								}
								delete b;
							}
							return true;
						});
					}
					d.isBindSet = true;
				}
			}
		}
		if (views.length > 0) {
			cmspad_views(views);
		}
		delete views;
	},
	_cmspad_form_func: function(){
		for (fi = 0, fl = document.forms.length; fi < fl; fi++) {
			f = document.forms[fi];
			if(!f){
				continue;
			}
			if (!f.isBindSet) {
				fb = f.getAttribute('bind');
				if (fb) {
					f.onsubmit = function(){
						b = cmspad.core._cmspad_bind_func(this);
						if (b) {
							if (b.validator) {
								if (!eval(b.validator)) {
									return false;
								}
							}
							if (this.encoding.toLowerCase() == 'multipart/form-data') {
								aTime = new Date().getTime();
								if (cmspad.security.encrypt) {
									aKey = cmspad.security.md5('_form&' + aTime);
									aArgs = 'cpda[]=' + cmspad.security.encrypt(b.portlet, aKey) + '&cpda[]=' + cmspad.security.encrypt(b.method, aKey);
								} else {
									aArgs = 'cpda[]=' + encodeURIComponent(b.portlet) + '&cpda[]=' + encodeURIComponent(b.method);
								}
								url = cmspad.REQUEST_URI + (cmspad.REQUEST_URI.indexOf('?') == -1 ? '?' : '&') + aArgs;
								cmspad.core._upload('_form', this, url, aTime);
								return true;
							} else {
								cmspad_form(b.portlet, b.method, cmspad.core.getFormData(this, false));
								return false;
							}
						} else {
							return true;
						}
						delete b;
					};
				}
				f.isBindSet = true;
				delete fb;
			}
		}
	},
	_cmspad_link_func: function(){
		ais = document.getElementsByTagName('a');
		for (i = 0, l = ais.length; i < l; i++) {
			a = ais[i];
			ab = a.getAttribute('bind');
			if (ab && !a.isBindSet) {
				a.onclick = function(){
					b = cmspad.core._cmspad_bind_func(this);
					if (b) {
						if (b.validator) {
							if (!eval(b.validator)) {
								return false;
							}
						}
						if (b.arguments) {
							cmspad_link(b.portlet, b.method, b.arguments);
						} else {
							cmspad_link(b.portlet, b.method);
						}
					}
					delete b;
					return false;
				};
				a.isBindSet = true;
			}
			delete ab;
		}
	},
	getBindData: function(t, e){
		var f = '';
		switch (t) {
			case 'json':
			case 'j':
				f = '_json';
				break;
			case 'form':
			case 'f':
				f = '_form';
				break;
			case 'link':
			case 'l':
				f = '_link';
				break;
			case 'view':
			case 'v':
				f = '_view';
				break;
			case 'call':
			case 'c':
				f = '_call';
				break;
			default:
				return null;
		}
		b = this.getExprData(e);
		if (b) {
			if (b.validator) {
				if (!eval(b.validator)) {
					return false;
				}
			}
			if (b.arguments) {
				return this.getPostData(f, [b.portlet, b.method, b.arguments]);
			} else {
				return this.getPostData(f, [b.portlet, b.method]);
			}
		} else {
			return null;
		}
	},
	initialize: function(){
		this._cmspad_view_func();
		this._cmspad_form_func();
		this._cmspad_link_func();
	}
};